package org.nudt.video.service

import jakarta.persistence.criteria.Predicate
import org.nudt.common.exception.BadRequestException
import org.nudt.common.model.PageData
import org.nudt.common.model.PlayLog
import org.nudt.common.model.Type
import org.nudt.common.model.Video
import org.nudt.common.model.vo.VideoVO
import org.nudt.common.repository.PlayLogRepository
import org.nudt.common.repository.TypeRepository
import org.nudt.common.repository.VideoRepository
import org.springframework.data.domain.Pageable
import org.springframework.data.jpa.domain.Specification
import org.springframework.stereotype.Service
import org.springframework.transaction.annotation.Transactional


@Service
class VideoService(
    private val videoRepository: VideoRepository,
    private val typeRepository: TypeRepository,
    private val playLogRepository: PlayLogRepository
) {
    
    fun getVideoTypeList(): MutableList<Type> {
        return typeRepository.findAll()
    }
    
    /**
     * 根据大类获取视频列表，并支持分页。
     *
     * @param videoClass 视频大类
     * @param pageable 分页信息
     * @return 视频列表
     */
    fun getVideoListByVideoClass(videoClass: Int, pageable: Pageable): PageData<VideoVO?> {
        val result = videoRepository.getByVideoClassAndStatusOrderByUpdatedAtDescIdDesc(videoClass, true, pageable).map { VideoVO.of(it) }
        return PageData(result.number + 1, result.size, result.totalElements, result.content)
    }
    
    /**
     * 根据类型获取推荐视频列表，并支持分页。
     *
     * @param typeId 视频类型
     * @param pageable 分页信息
     * @return 视频列表
     */
    fun getVideoListRecommendByType(typeId: Int, pageable: Pageable): List<VideoVO> {
        return videoRepository.getVideosOrderByRand(typeId, pageable).map { VideoVO.of(it) }
    }
    
    /**
     * 根据视频ID获取视频信息，并在访问后添加一条播放日志。
     *
     * @param id 视频ID
     * @return 视频信息
     */
    @Transactional
    fun getVideoById(id: Int, appid: String?): Video {
        val video = videoRepository.findById(id).orElseThrow { throw BadRequestException("视频数据未找到") }
        val playLog = PlayLog(videoId = video.id, appid = appid)
        playLogRepository.save(playLog)
        return video
    }
    
    /**
     * 根据横幅级别获取视频列表。
     *
     * @return 视频列表
     */
    fun getBannerVideoList(): List<VideoVO> {
        // 调用videoRepository的getByVodLevel方法，传入banner参数，获取对应的视频列表
        return videoRepository.getByLevel(1).map { VideoVO.of(it) }
    }
    
    /**
     * 根据关键字搜索视频列表，不区分大小写。
     *
     * @param keyword 搜索关键字
     * @return 视频列表
     */
    fun searchVideoList(keyword: String, pageable: Pageable): PageData<VideoVO> {
        // 创建一个Specification对象，用于构建查询条件
        val spec = Specification<Video> { root, query, cBuilder ->
            val predicates: MutableList<Predicate> = ArrayList()
            val videoNameCondition = cBuilder.like(root.get("videoName"), "%${keyword}%")
            val actorCondition = cBuilder.like(root.get("actor"), "%${keyword}%")
            val condition = cBuilder.or(videoNameCondition, actorCondition)
            predicates.add(condition)
            // 返回查询条件
            return@Specification cBuilder.and(*predicates.toTypedArray())
            
        }
        // 根据查询条件分页查询视频列表，并返回VideoVO对象
        val result = videoRepository.findAll(spec, pageable).map { VideoVO.of(it) }
        return PageData(result.number + 1, result.size, result.totalElements, result.content)
    }
    
    /**
     * 根据类型、地区、年份等条件过滤视频列表，并支持分页。
     *
     * @param type 视频类型
     * @param area 地区
     * @param year 年份
     * @param minYear 最小年份
     * @param pageable 分页信息
     * @return 视频列表
     */
    fun filterVideoList(type: Int, area: String?, year: Int?, minYear: Int, pageable: Pageable): PageData<VideoVO> {
        // 创建一个Specification对象，用于构建查询条件
        val spec = Specification<Video> { root, query, cBuilder ->
            val predicates: MutableList<Predicate> = ArrayList()
            // 如果类型大于0，则添加类型条件
            if (type > 0) {
                val typeCondition = cBuilder.equal(root.get<Int>("typeId"), type)
                predicates.add(typeCondition)
            }
            // 如果地区为“中国”、“美国”、“韩国”、“日本”，则添加地区条件
            if (area.equals("中国") || area.equals("美国") || area.equals("韩国") || area.equals("日本")) {
                val areaCondition = cBuilder.like(root.get("area"), "%$area%")
                predicates.add(areaCondition)
            }
            
            // 如果地区为“其他地区”，则添加地区条件
            if (area == "其他地区") {
                val areaConditionChina = cBuilder.notLike(root.get("area"), "%中国%")
                val areaConditionUSA = cBuilder.notLike(root.get("area"), "%美国%")
                val areaConditionKorea = cBuilder.notLike(root.get("area"), "%韩国%")
                val areaConditionJapan = cBuilder.notLike(root.get("area"), "%日本%")
                predicates.add(areaConditionChina)
                predicates.add(areaConditionUSA)
                predicates.add(areaConditionKorea)
                predicates.add(areaConditionJapan)
            }
            // 如果年份不为空，则添加年份条件
            if (year != null) {
                // 如果年份大于最小年份，则添加年份条件
                if (year > minYear) {
                    val yearCondition = cBuilder.equal(root.get<Int>("year"), year)
                    predicates.add(yearCondition)
                    // 否则，添加年份小于最小年份+1的条件
                } else {
                    val yearCondition = cBuilder.lessThan(root.get("year"), minYear + 1)
                    predicates.add(yearCondition)
                }
            }
            // 返回查询条件
            return@Specification cBuilder.and(*predicates.toTypedArray())
            
        }
        // 根据查询条件分页查询视频列表，并返回VideoVO对象
        val result = videoRepository.findAll(spec, pageable).map { VideoVO.of(it) }
        return PageData(result.number + 1, result.size, result.totalElements, result.content)
    }
    
    
}